#include "Canvas.hpp"

#include "ElapsedTimer.hpp"
#include "SharedUtil.hpp"
#include "LineBuffer.hpp"

#include <QPainter>
#include <QMouseEvent>

//#define DRAW_INTERSECT_POINTS

class Canvas::CanvasPrivate
{
public:

  CanvasPrivate( Canvas* me ) : m_self( me ) {
  }

  void init() {
    reset();

#if 0
    for( int idx = 0; idx < 1800; ++idx ) {
      float xpos = idx;
      float ypos = sin( idx*3.14159/180 ) * 50;
      m_spine << QPointF(xpos, ypos);
    }
    m_spine << m_spine.first();
    m_spine.translate( 10, 200 );
#endif
  }

  void reset() {
    m_spine.clear();
    m_offset.clear();

    m_intersectPoints1.clear();
    m_intersectPoints2.clear();
  }

  void generateBuffer() {
    ElapsedTimer elapsedTimer( "GenerateBuffer" );
    m_offset = theLineBuffer->getOffset( m_spine, 20 );

#ifdef DRAW_INTERSECT_POINTS
    SharedUtil::getIntersectPoints( m_offset.first(), m_offset.last(), m_intersectPoints1, m_intersectPoints2 );
    m_intersectPoints1 += SharedUtil::getSelfIntersectPoints( m_offset.first() );
    m_intersectPoints2 = SharedUtil::getSelfIntersectPoints( m_offset.last() );
#endif
  }

  void drawSpine( QPainter& painter ) {
    painter.save();
    QPen pen;
    pen.setWidth( 2 );
    painter.setPen( pen );
    painter.drawPolyline( m_spine );
    painter.restore();
  }

  void drawOffset( QPainter& painter ) {
    painter.save();

    int idx = 0;
    QColor colors[2] = { Qt::red, Qt::blue };

    QPen pen( Qt::DashLine );
    Q_FOREACH( const QPolygonF& offset, m_offset ) {
      pen.setColor( colors[idx] );
      painter.setPen( pen );
      painter.drawPolyline( offset );
      idx = 1-idx;
    }

    painter.restore();
  }

  void drawIntersectPoints( QPainter& painter ) {
    painter.save();

    painter.setRenderHint( QPainter::Antialiasing );

    painter.setPen( QPen( Qt::red, 2 ) );
    painter.setBrush( Qt::yellow );

    Q_FOREACH( const QPolygonF& pts, m_intersectPoints1 ) {
      Q_FOREACH( const QPointF& pt, pts ) {
        painter.drawEllipse( pt, 5, 5 );
      }
    }

    Q_FOREACH( const QPolygonF& pts, m_intersectPoints2 ) {
      Q_FOREACH( const QPointF& pt, pts ) {
        painter.drawEllipse( pt, 5, 5 );
      }
    }

    painter.restore();
  }

  Canvas*           m_self;

  QPolygonF         m_spine;
  QList<QPolygonF>  m_offset;

  QList<QPolygonF>  m_intersectPoints1;
  QList<QPolygonF>  m_intersectPoints2;
};

Canvas::Canvas( QWidget* parent ) : QFrame( parent ), _pd( new CanvasPrivate( this ) )
{
  _pd->init();
}

Canvas::~Canvas()
{
}

void Canvas::paintEvent( QPaintEvent* event )
{
  QFrame::paintEvent( event );

  QPainter painter( this );
  painter.setRenderHint( QPainter::Antialiasing );
  _pd->drawSpine( painter );
  _pd->drawOffset( painter );

#ifdef DRAW_INTERSECT_POINTS
  _pd->drawIntersectPoints( painter );
#endif
  update();
}

void Canvas::mousePressEvent( QMouseEvent* event )
{
  switch( event->button() ) {
  case Qt::LeftButton:    _pd->m_spine << event->pos(); break;

  case Qt::MiddleButton:  _pd->reset();                 break;

  case Qt::RightButton:   _pd->generateBuffer();        break;
  }
}

void Canvas::mouseMoveEvent( QMouseEvent* event )
{
  emit( showMessage( QString( "%1, %2").arg( event->posF().x() ).arg( event->posF().y() ) ) );
}
